<?php

namespace app\admin\controller;

use app\common\controller\Backend;
use think\Db;

/**
 * 商场订单
 *
 * @icon fa fa-circle-o
 */
class ShopOrder extends Backend
{

    /**
     * ShopOrder模型对象
     * @var \app\admin\model\ShopOrder
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\ShopOrder;

    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */


    /**
     * 查看
     */
    public function index()
    {
        //当前是否为关联查询
        $this->relationSearch = true;
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            $filter = $this->request->get("filter", '');
            $where = json_decode($filter, true) ?? [];
            if(isset($where['province_id'])){
                $where['address.province_id'] = $where['province_id'];
                unset($where['province_id']);
            }
            if(isset($where['city_id'])){
                $where['address.city_id'] = $where['city_id'];
                unset($where['city_id']);
            }
            if(isset($where['area_id'])){
                $where['address.area_id'] = $where['area_id'];
                unset($where['area_id']);
            }
//            return $where;
            $list = $this->model
                    ->with(['user','address'])
                    ->where($where)
                    ->order($sort, $order)
                    ->paginate($limit);

            foreach ($list as $row) {
                
                $row->getRelation('user')->visible(['nickname']);
				$row->getRelation('address')->visible(['name','mobile','province_id','city_id','area_id','address']);
                $province = \app\admin\model\Area::where(['id'=>$row['address']['province_id']])
                    ->value('name');
                $city = \app\admin\model\Area::where(['id'=>$row['address']['city_id']])
                    ->value('name');
                $area = \app\admin\model\Area::where(['id'=>$row['address']['area_id']])
                    ->value('name');
                $row['region'] = $province.'/'.$city.'/'.$area;
            }

            $total = $this->model->with(['user','address'])->where($where)->where(['shop_order.paid'=>1])->order($sort, $order)->sum('shop_order.payamount');
            $payment = $this->model->with(['user','address'])->where($where)->where(['shop_order.paid'=>1,'shop_order.status'=>['in',[0,1,2,3]]])->order($sort, $order)->sum('shop_order.payamount');
//            $order_ids = $this->model->with(['user','address'])->where($where)->where(['shop_order.paid'=>1])->order($sort, $order)->column('shop_order.id');
//            $addon = \app\admin\model\OrderInstall::where(['order_id'=>['in',$order_ids]])->sum('extra_money');
            $chargeback = $this->model->with(['user','address'])->where($where)->where(['shop_order.paid'=>1,'shop_order.status'=>['in', [100,200]]])->order($sort, $order)->sum('shop_order.payamount');

            $result = array("total" => $list->total(), "rows" => $list->items(), "extend" => ['total' => $total, 'payment' => $payment, 'chargeback' => $chargeback]);

            return json($result);
        }
        return $this->view->fetch();
    }

    public function cancel($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            if($row['paid'] == 0){
                $row['payamount'] = 0;
            }
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
            $this->error(__('You have no permission'));
        }
        if (false === $this->request->isPost()) {

            $this->view->assign('row', $row);
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);
        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                $row->validateFailException()->validate($validate);
            }

            $amount = $params['refund'] * 100;
            if($amount > 0){
                // $amount = 1;// 测试阶段，正式上线记得关闭
                $order_no = $params['order_no'];

                // 退款
                $result = $this->Refund('',$order_no,$amount);
                if($result['code'] != 1){
                    $this->error($result['msg']);
                }

            }
            $params['refund_status'] = 1;
            $result = $row->allowField(true)->save($params);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if (false === $result) {
            $this->error(__('No rows were updated'));
        }
        $this->success();
    }
    
    
    
    //退款
    public function Refund($transaction_id,$out_trade_no,$amount){ //商户订单号,微信生成的退款订单号 二选一即可
        $time=time();
        $out_refund_no=$time.rand(1111,9999);
        $refundData=[
            'out_refund_no'=>$out_refund_no,
            'reason'=>'用户取消订单',
            // 'notify_url'=>$this->config['refund_notify_url'],
            'funds_account'=>'AVAILABLE',
            'amount'=>[
                'refund'=>$amount, //退款标价金额，单位为分，可以做部分退款
                'total'=>$amount, //订单总金额，单位为分
                'currency'=>'CNY'
            ]
        ];
        if(!$transaction_id){ //商户订单号,微信生成的退款订单号 二选一即可
            if(!$out_trade_no){
                return ['code'=>0,'msg'=>'退款订单号不能为空'];
            }else{
                $refundData['out_trade_no']=$out_trade_no;
            }
        }else{
            $refundData['transaction_id']=$transaction_id;
        }
        $url='https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
        $urlarr = parse_url($url); //拆解为：[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native]
        $mchid = '1709517563';//商户ID
        $xlid = '4C59EB16EAA829C2E0DEC4244E6C41633768D1DF';//证书序列号
        $refundData=json_encode($refundData);
        $nonce = $this->getNonceStr();
        $key = $this->getSign($refundData,$urlarr['path'],$nonce,$time);
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"',$mchid,$xlid,$nonce,$time,$key);
        $header  = array(
            'Accept: application/json',
            'Content-Type: application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 '.$token
        );
        $res=$this->curl_post_https($url,$refundData,$header);
        $res_array=json_decode($res,true);
        if(isset($res_array['status'])){
            if($res_array['status']=='PROCESSING' || $res_array['status']=='SUCCESS'){
                return ['code'=>1,'msg'=>'退款成功'];
            }else{
                return ['code'=>0,'msg'=>$res_array['message']];
            }
            
        }else{
            return ['code'=>0,'msg'=>$res_array['message']];
        }
    }


    //获取随机字符串
    public function getNonceStr(){
        $strs="QWERTYUIOPASDFGHJKLZXCVBNM1234567890";
        $name=substr(str_shuffle($strs),mt_rand(0,strlen($strs)-11),32);
        return $name;
    }

    //微信支付签名
    function getSign($data=array(),$url,$randstr,$time){
        $str = "POST"."\n".$url."\n".$time."\n".$randstr."\n".$data."\n";
        $key = file_get_contents(ROOT_PATH . '/addons/epay/certs/apiclient_key.pem');//在商户平台下载的秘钥,读取到变量
        $str = $this->getSha256WithRSA($str,$key);
        return $str;
    }

    //调起支付的签名
    function getWechartSign($appid,$timeStamp,$noncestr,$prepay_id){
        $str = $appid."\n".$timeStamp."\n".$noncestr."\n".$prepay_id."\n";
        $key = file_get_contents(ROOT_PATH . '/addons/epay/certs/apiclient_key.pem');//在商户平台下载的秘钥,读取到变量
        $str = $this->getSha256WithRSA($str,$key);
        return $str;
    }

    //加密
    public function getSha256WithRSA($content, $privateKey){
        $binary_signature = "";
        $algo = "SHA256";
        openssl_sign($content, $binary_signature, $privateKey, $algo);
        $sign = base64_encode($binary_signature);
        return $sign;
    }

    /* PHP CURL HTTPS POST */
    function curl_post_https($url,$data,$header){ // 模拟提交数据函数
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在，如果出错则修改为0，默认为1
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        $tmpInfo = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            echo 'Errno'.curl_error($curl);//捕抓异常
        }
        curl_close($curl); // 关闭CURL会话
        return $tmpInfo; // 返回数据，json格式
    }
}
